//<Super Awesome RTS>
//
//Copyright 2012 Trevin Liberty
//GNU GPL v3
//Author: Trevin Liberty
//
//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//TODO: Change most Point<float> to Point<int>

#include <allegro5\allegro.h>
#include <allegro5\altime.h>
#include <allegro5\allegro_primitives.h>
#include <allegro5\allegro_image.h>
#include <allegro5\allegro_font.h>
#include <allegro5\allegro_ttf.h>

#include <math.h>
#include <algorithm>
#include <iostream>
#include <list>

using namespace std;

#include "Allegro_Misc.h"
#include "Cursor.h"
#include "camera.h"
#include "Map_Loader.h"
#include "Structs.h"
#include "Point.h"
#include "GameWorld.h"
#include "Doohickeys\Archer.h"
#include "Doohickeys\Swordsmen.h"

//Global Constant
const int MAX_FPS = 60;

GameWorld* gameWorld;

int main() {
	int windowWidth = 800;
	int windowHeight = 600;
	int windowedWidth = windowWidth;
	int windowedHeight = windowHeight;
	int fullScreenWidth;
	int fullScreenHeight;
	Point<int> windowPos;

	bool done = false;
	bool redraw = true;
	bool fullScreen = false;

	bool pressedKeys[ALLEGRO_KEY_MAX];

	imageArray base;
	imageArray fringe;

	//allegro variable
	ALLEGRO_DISPLAY *display = NULL;
	ALLEGRO_EVENT_QUEUE *event_queue = NULL;
	ALLEGRO_TIMER *timer = NULL;
	Map* map = new Map;

	allegroInit(windowWidth, windowHeight, MAX_FPS, display, event_queue, timer);

	ALLEGRO_MONITOR_INFO* info = new ALLEGRO_MONITOR_INFO;
	al_get_monitor_info(0, info);
	windowWidth = info->x2 - 128;
	windowHeight = info->y2 - 128;
	windowedWidth = windowWidth;
	windowedHeight = windowHeight;
	fullScreenWidth = info->x2;
	fullScreenHeight = info->y2;
	al_get_window_position(display, &windowPos.x, &windowPos.y);

	loadImages(base, fringe);

	list<Entity*>* entities = loadMap(map);
	list<Entity*>::iterator it = entities->begin();

	gameWorld = new GameWorld(map, windowWidth, windowHeight, display);
	gameWorld->initGameWorld(base, fringe);

	for(it; it != entities->end(); ++it)
		gameWorld->addEntity(*it);

	int time = al_get_time();
	int frame = 0;

	int lastRClick = al_get_time();

	for(int i = 0; i < ALLEGRO_KEY_MAX; i++)
		pressedKeys[i] = false;

	ALLEGRO_MOUSE_STATE state;

	list<Entity*>::iterator itE;

	al_start_timer(timer);

	while(!done) {
		ALLEGRO_EVENT ev;
		al_wait_for_event(event_queue, &ev);

		switch(ev.type) {

		case ALLEGRO_EVENT_DISPLAY_CLOSE:
			done = true;
			break;

		case ALLEGRO_EVENT_TIMER:

			gameWorld->update();

			al_get_mouse_state(&state);

			if(pressedKeys[ALLEGRO_KEY_DOWN] == true || pressedKeys[ALLEGRO_KEY_S] == true)
				gameWorld->getCamera()->addToY(10);
			if(pressedKeys[ALLEGRO_KEY_UP] == true || pressedKeys[ALLEGRO_KEY_W] == true)
				gameWorld->getCamera()->addToY(-10);
			if(pressedKeys[ALLEGRO_KEY_LEFT] == true || pressedKeys[ALLEGRO_KEY_A] == true)
				gameWorld->getCamera()->addToX(-10);
			if(pressedKeys[ALLEGRO_KEY_RIGHT] == true || pressedKeys[ALLEGRO_KEY_D] == true)
				gameWorld->getCamera()->addToX(10);

			redraw = true;
			break;

		case ALLEGRO_EVENT_KEY_DOWN:
			if(ev.keyboard.keycode == ALLEGRO_KEY_DOWN)
				pressedKeys[ALLEGRO_KEY_DOWN] = true;
			else if(ev.keyboard.keycode == ALLEGRO_KEY_UP)
				pressedKeys[ALLEGRO_KEY_UP] = true;
			else if(ev.keyboard.keycode == ALLEGRO_KEY_LEFT)
				pressedKeys[ALLEGRO_KEY_LEFT] = true;
			else if(ev.keyboard.keycode == ALLEGRO_KEY_RIGHT)
				pressedKeys[ALLEGRO_KEY_RIGHT] = true;
			else if(ev.keyboard.keycode == ALLEGRO_KEY_A)
				pressedKeys[ALLEGRO_KEY_A] = true;
			else if(ev.keyboard.keycode == ALLEGRO_KEY_S)
				pressedKeys[ALLEGRO_KEY_S] = true;
			else if(ev.keyboard.keycode == ALLEGRO_KEY_D)
				pressedKeys[ALLEGRO_KEY_D] = true;
			else if(ev.keyboard.keycode == ALLEGRO_KEY_W)
				pressedKeys[ALLEGRO_KEY_W] = true;
			else if(ev.keyboard.keycode == ALLEGRO_KEY_F) {
				if(fullScreen == false) {
					al_toggle_display_flag(display, ALLEGRO_FULLSCREEN_WINDOW, true);
					fullScreen = true;
					gameWorld->setWindowSize(fullScreenWidth, fullScreenHeight);
				}
				else {
					al_toggle_display_flag(display, ALLEGRO_FULLSCREEN_WINDOW, false);
					fullScreen = false;
					al_resize_display(display, windowedWidth, windowedHeight);
					al_set_window_position(display, 0, 0);
					gameWorld->setWindowSize(windowedWidth, windowedHeight);
				}
			}
			else if(ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
				done = true;
			break;

		case ALLEGRO_EVENT_KEY_UP:
			if(ev.keyboard.keycode == ALLEGRO_KEY_DOWN)
				pressedKeys[ALLEGRO_KEY_DOWN] = false;
			else if(ev.keyboard.keycode == ALLEGRO_KEY_UP)
				pressedKeys[ALLEGRO_KEY_UP] = false;
			else if(ev.keyboard.keycode == ALLEGRO_KEY_LEFT)
				pressedKeys[ALLEGRO_KEY_LEFT] = false;
			else if(ev.keyboard.keycode == ALLEGRO_KEY_RIGHT)
				pressedKeys[ALLEGRO_KEY_RIGHT] = false;
			else if(ev.keyboard.keycode == ALLEGRO_KEY_A)
				pressedKeys[ALLEGRO_KEY_A] = false;
			else if(ev.keyboard.keycode == ALLEGRO_KEY_S)
				pressedKeys[ALLEGRO_KEY_S] = false;
			else if(ev.keyboard.keycode == ALLEGRO_KEY_D)
				pressedKeys[ALLEGRO_KEY_D] = false;
			else if(ev.keyboard.keycode == ALLEGRO_KEY_W)
				pressedKeys[ALLEGRO_KEY_W] = false;
			break;

		case ALLEGRO_EVENT_MOUSE_AXES:
			break;

		case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN:
			al_get_mouse_state(&state);
			if(ev.mouse.button == 1) {
				gameWorld->leftClickDown(Point<float>(state.x, state.y));
			}
			if(ev.mouse.button == 2) {
				if((al_get_time() - lastRClick) > .7) {
					lastRClick = al_get_time();
					gameWorld->rightClickDown(Point<float>(state.x, state.y));
				}
			}
			if(ev.mouse.button == 3) {
				gameWorld->middleClickDown(Point<float>(state.x, state.y));
			}
			break;

		case ALLEGRO_EVENT_MOUSE_BUTTON_UP:
			al_get_mouse_state(&state);
			if(ev.mouse.button == 1) {
				gameWorld->leftClickUp(Point<float>(state.x, state.y));
			}
			if(ev.mouse.button == 2) {
				gameWorld->rightClickUp(Point<float>(state.x, state.y));
			}
			if(ev.mouse.button == 3)
				gameWorld->middleClickUp(Point<float>(state.x, state.y));
			break;
		}
		if(redraw && al_is_event_queue_empty(event_queue))
		{
			redraw = false;
			gameWorld->draw();
			al_get_mouse_state(&state);
			al_flip_display();
			al_clear_to_color(al_map_rgb(0,0,0));

			//cout << frame/(al_get_time() - time) << endl;
			frame++;
		}
	}

	cout << "START FINISH NOW" << endl;

	al_destroy_display(display);

	delete gameWorld;

	cout << endl << "RETURN";
	return 0;
}